package com.sky.aspect;

import com.sky.annotation.AutoFile;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 公共字段自动填充的切面类
 */
@Aspect// 定义切面类的注解
@Component
@Slf4j
public class AutoFileAspect {
    /**
     * 定义切入点方法
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFile)")//定义切入点位置的注解
    public void pt() {
    }

    /*
    定义前置通知进行公共字段自动赋值方法
     */
    @Before("pt()")//对于切入点方法进行前置通知增强
    public void autoFillPointCut(JoinPoint joinPoint) {
        log.info("进行公共字段填充");
        //1.获取mapper操作类型 Insert or Update
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//通过连接点获取方法的签名对象
        Method method = signature.getMethod();//获取方法对象
        AutoFile annotation = method.getAnnotation(AutoFile.class);//获取方法上的AutoFill注解
        OperationType value = annotation.value();//获取注解里定义的操作类型
        //2.获取传入的实体类对象
        Object[] args = joinPoint.getArgs();//获取需要增强方法的所有参数
        if (args == null || args.length == 0) {
            return;
        }//判断参数是否为空
        Object entity = args[0];//获取传入的实体对象
        //3.获取自动赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();
        //4.根据类型进行赋值
        if (value.equals(OperationType.INSERT)) {
            //对于Insert类型的操作进行自动赋值 执行setCreateTime setUpdateTime setCreateUser setUpdateUser
            //通过反射调用方法进行赋值
            try {
                Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);//通过反射获取方法对象
                Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);//通过反射获取方法对象
                Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);//通过反射获取方法对象
                Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);//通过反射获取方法对象
                setCreateTime.invoke(entity, now);//反射执行方法
                setUpdateTime.invoke(entity, now);//反射执行方法
                setCreateUser.invoke(entity, currentId);//反射执行方法
                setUpdateUser.invoke(entity, currentId);//反射执行方法
            } catch (Exception e) {
                log.error("自动赋值失败");
            }

        } else {
            //对于update类型的操作进行自动赋值
            //通过反射调用方法进行赋值
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);//通过反射获取方法对象
                Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);//通过反射获取方法对象
                setUpdateTime.invoke(entity, now);//反射执行方法
                setUpdateUser.invoke(entity, currentId);//反射执行方法
            } catch (Exception e) {
                log.error("自动赋值失败");
            }
        }
    }


}

